package com.ruiysoft.security.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruiysoft.entity.sys.SysOauthClient;
import com.ruiysoft.service.sys.ISysOauthClientService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.Optional;
import java.util.function.Function;

/**
 * Created by 化增光 on 2018/10/28.
 */
@Service("redisClientDetailsService")
public class RedisClientDetailsService implements ClientDetailsService {

    @Resource
    private RedisTemplate<String,SysOauthClient> clientRedisTemplate;

    @Resource
    ISysOauthClientService iSysOauthClientService;

    private final String clientKey = "OAUTH_CLIENT:";
    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
        SysOauthClient sysOauthClient = null;
        sysOauthClient = clientRedisTemplate.opsForValue().get(clientKey+clientId);
        if (null == sysOauthClient){
            sysOauthClient = iSysOauthClientService.getOne(new QueryWrapper<SysOauthClient>().eq("client_id",clientId));
            if (null == sysOauthClient ){
                throw new NoSuchClientException("Client ID not found");
            }
            clientRedisTemplate.opsForValue().set(clientKey+clientId,sysOauthClient);
        }
        return Optional.of(sysOauthClient).map(entityToDomain).<ClientRegistrationException>orElseThrow(() -> new NoSuchClientException("Client ID not found"));

    }
    private final Function<? super SysOauthClient, ? extends BaseClientDetails> entityToDomain = entity -> {
        BaseClientDetails clientDetails = new BaseClientDetails();

        clientDetails.setClientId(entity.getClientId());
        clientDetails.setClientSecret(entity.getClientSecret());

        clientDetails.setAccessTokenValiditySeconds(entity.getAccessTokenValidity());
        clientDetails.setRefreshTokenValiditySeconds(entity.getRefreshTokenValidity());

        clientDetails.setAuthorizedGrantTypes(Arrays.asList(StringUtils.split(entity.getAuthorizedGrantTypes(),",")));

        clientDetails.setScope(Arrays.asList(StringUtils.split(entity.getScope(),",")));

        clientDetails.setAdditionalInformation(Collections.emptyMap());
        return clientDetails;
    };
}